using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Admin.NET.Application.Entity;
using Admin.NET.Application.Service.Report.Dto;
using Admin.NET.Core;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using SqlSugar;

namespace Admin.NET.Application;

/// <summary>
/// 区域管理
/// </summary>
[ApiDescriptionSettings(new string[] { "业务应用" }, Order = 100)]
public class BuildingService : IDynamicApiController, ITransient, IPrivateDependency
{
	private readonly SqlSugarRepository<Building> _rep;

	public BuildingService(SqlSugarRepository<Building> rep)
	{
		_rep = rep;
	}

	/// <summary>
	/// 分页查询区域
	/// </summary>
	/// <param name="input"></param>
	/// <returns></returns>
	[HttpGet("/building/page")]
	public async Task<dynamic> Page([FromQuery] BuildingInput input)
	{
		ISugarQueryable<Building> query = _rep.Context.Queryable<Building>().WhereIF(!string.IsNullOrWhiteSpace(input.Name), (Building u) => u.Name.Contains(input.Name.Trim()));
		query = query.OrderBuilder(input);
		return await query.ToPagedListAsync(input.Page, input.PageSize);
	}

	/// <summary>
	/// 增加区域
	/// </summary>
	/// <param name="input"></param>
	/// <returns></returns>
	[HttpPost("/building/add")]
	public async Task Add(AddBuildingInput input)
	{
		Building entity = input.Adapt<Building>();
		await _rep.InsertAsync(entity);
	}

	/// <summary>
	/// 删除区域
	/// </summary>
	/// <param name="input"></param>
	/// <returns></returns>
	[HttpPost("/building/delete")]
	public async Task Delete(DeleteBuildingInput input)
	{
		if (await (from w in _rep.Context.Queryable<Room>()
			where w.BuildingId == input.Id
			select w).CountAsync() > 0)
		{
			throw Oops.Bah("请先删除区域下的房间，再进行操作");
		}
		Building entity = await _rep.GetFirstAsync((Building u) => u.Id == input.Id);
		await _rep.DeleteAsync(entity);
	}

	/// <summary>
	/// 更新区域
	/// </summary>
	/// <param name="input"></param>
	/// <returns></returns>
	[HttpPost("/building/edit")]
	public async Task Update(UpdateBuildingInput input)
	{
		Building entity = input.Adapt<Building>();
		await _rep.UpdateAsync(entity);
	}

	/// <summary>
	/// 获取区域列表
	/// </summary>
	/// <param name="input"></param>
	/// <returns></returns>
	[HttpGet("/building/list")]
	public async Task<dynamic> List()
	{
		List<Building> result = await (from u in _rep.AsQueryable()
			orderby u.CreateTime
			select u).ToListAsync();
		List<Building> root = result.Where((Building w) => w.Pid == 0).ToList();
		List<long> ids = new List<long>();
		foreach (Building item in root)
		{
			MapChild(item, result, ids);
		}
		return root;
	}

	/// <summary>
	/// 获取区域列表 tree select
	/// </summary>
	/// <param name="input"></param>
	/// <returns></returns>
	[HttpGet("/building/treeselect")]
	public async Task<dynamic> TreeSelect()
	{
		List<Building> result = await (from u in _rep.AsQueryable()
			orderby u.CreateTime
			select u).ToListAsync();
		List<BuildingOut2> root = (from w in result
			where w.Pid == 0
			select new BuildingOut2
			{
				label = w.Name,
				value = w.Id,
				children = new List<BuildingOut2>()
			}).ToList();
		List<long> ids = new List<long>();
		foreach (BuildingOut2 item in root)
		{
			MapChild2(item, result, ids);
		}
		return root;
	}

	private void MapChild2(BuildingOut2 item, List<Building> list, List<long> ids)
	{
		if (ids.Contains(item.value))
		{
			return;
		}
		ids.Add(item.value);
		List<BuildingOut2> children = (from w in list
			where w.Pid == item.value
			select new BuildingOut2
			{
				value = w.Id,
				label = w.Name,
				children = new List<BuildingOut2>()
			}).ToList();
		if (children.Count <= 0)
		{
			return;
		}
		item.children.AddRange(children);
		foreach (BuildingOut2 child in children)
		{
			MapChild2(child, list, ids);
		}
	}

	private void MapChild(Building item, List<Building> list, List<long> ids)
	{
		if (ids.Contains(item.Id))
		{
			return;
		}
		ids.Add(item.Id);
		item.Children = new List<Building>();
		List<Building> children = list.Where((Building w) => w.Pid == item.Id).ToList();
		if (children.Count <= 0)
		{
			return;
		}
		item.Children.AddRange(children);
		foreach (Building child in children)
		{
			MapChild(child, list, ids);
		}
	}

	private void MapParent(BuildingOut item, List<Building> list, BuildingOut item2)
	{
		if (item.Pid == 0)
		{
			return;
		}
		Building tmp = list.Where((Building w) => w.Id == item.Pid).FirstOrDefault();
		if (tmp != null)
		{
			item.Parent = tmp.Adapt<BuildingOut>();
			item2.ParentNames.Add(tmp.Name);
			if (tmp.Id != 0)
			{
				MapParent(item.Parent, list, item2);
			}
		}
	}

	/// <summary>
	/// 左侧的树
	/// </summary>
	/// <param name="type">1代表仅区域，2代表需要房间,3包含电表</param>
	/// <returns></returns>
	[HttpGet("/building/lefttree")]
	public async Task<dynamic> GetBuildingLeftTree([FromQuery] int type, [FromQuery] int? isPublic)
	{
		List<Building> result = await (from u in _rep.AsQueryable()
			orderby u.CreateTime
			select u).ToListAsync();
		List<RoomTree> root = (from w in result
			where w.Pid == 0
			select new RoomTree
			{
				Name = w.Name,
				Id = w.Id,
				BuildingId = w.Id,
				Icon = "<el-icon><Discount /></el-icon>",
				Type = 0,
				Children = new List<RoomTree>()
			}).ToList();
		List<Room> rooms = new List<Room>();
		List<ElectricMeter> electricMeters = new List<ElectricMeter>();
		if (root.Count > 0)
		{
			if (type == 2 || type == 3)
			{
				rooms = await _rep.Context.Queryable<Room>().ToListAsync();
			}
			if (type == 3)
			{
				electricMeters = await _rep.Context.Queryable<ElectricMeter>().WhereIF(isPublic.HasValue, (ElectricMeter u) => u.IsPublicMeter == true).ToListAsync();
			}
		}
		List<long> ids = new List<long>();
		foreach (RoomTree item in root)
		{
			MapChild3(item, result, ids, rooms, electricMeters);
		}
		RoomInfoTree roomInfoTree = new RoomInfoTree
		{
			RoomTrees = root
		};
		if (type == 3 && electricMeters.Count > 0)
		{
			List<RoomTree> noroom = (from w in electricMeters
				where !w.RoomId.HasValue
				select w into u
				select new RoomTree
				{
					Id = u.Id,
					Name = u.Name,
					Type = 2,
					Children = new List<RoomTree>()
				}).ToList();
			if (noroom.Count > 0)
			{
				roomInfoTree.RoomTrees.AddRange(noroom);
			}
		}
		return roomInfoTree;
	}

	private void MapChild3(RoomTree item, List<Building> list, List<long> ids, List<Room> rooms, List<ElectricMeter> electricMeters)
	{
		if (ids.Contains(item.Id))
		{
			return;
		}
		ids.Add(item.Id);
		item.Children = new List<RoomTree>();
		List<RoomTree> children = (from w in list
			where w.Pid == item.Id
			select new RoomTree
			{
				Name = w.Name,
				Id = w.Id,
				BuildingId = w.Id,
				Icon = "<el-icon><Discount /></el-icon>",
				Type = 0,
				Children = new List<RoomTree>()
			}).ToList();
		if (children.Count > 0)
		{
			item.Children.AddRange(children);
			foreach (RoomTree child in children)
			{
				MapChild3(child, list, ids, rooms, electricMeters);
			}
		}
		if (rooms.Count <= 0)
		{
			return;
		}
		List<RoomTree> tmprooms = (from w in rooms
			where w.BuildingId == item.Id
			select w into s
			select new RoomTree
			{
				Id = s.Id,
				Type = 1,
				BuildingId = s.BuildingId,
				Name = s.Name,
				Children = new List<RoomTree>()
			}).ToList();
		if (tmprooms.Count <= 0)
		{
			return;
		}
		item.Children.AddRange(tmprooms);
		if (electricMeters.Count <= 0)
		{
			return;
		}
		foreach (RoomTree room in tmprooms)
		{
			List<RoomTree> tmpmeters = (from w in electricMeters
				where w.RoomId == room.Id
				select w into s
				select new RoomTree
				{
					Id = s.Id,
					Type = 2,
					Name = s.Name,
					Children = new List<RoomTree>()
				}).ToList();
			if (tmpmeters.Count > 0)
			{
				room.Children.AddRange(tmpmeters);
			}
		}
	}
}
